package genedit.gui;

import genedit.model.Document;
import genedit.model.Workspace;
import genedit.model.graph.GraphDocument;
import genedit.model.graph.GraphElement;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

/**
 * Kontejnerska klasa koja se brine o stablu hijerarhije, pre svega njegovoj
 * inicijalizaciji.
 * 
 * @author Nikola
 * @version 1.3 18/12/13
 */
public class GProjectTree implements Observer {

	/**
	 * ScrollPane u kojem je smešten stablo kako bi moglo celo da stane, čak i
	 * ako je veće od prikaznog uređaja.
	 */
	protected JScrollPane scrollPane;

	/**
	 * Stablo hijerarhije.
	 */
	protected JTree tree;

	/**
	 * Singleton instanca kontejnera stabla.
	 */
	protected static GProjectTree projectTree = null;

	public JScrollPane getScrollPane() {
		return scrollPane;
	}

	public JTree getTree() {
		return tree;
	}

	protected GProjectTree() {
		tree = new JTree(new DefaultTreeModel(Workspace.getInstance()));
		tree.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyChar() == KeyEvent.VK_ENTER) {
					TreeNode element = (TreeNode) tree.getLastSelectedPathComponent();
					if (element instanceof Document) {
						GraphDocument gd = (GraphDocument) tree.getLastSelectedPathComponent();
						GMainFrame.getInstance().addGraphDocumentView(gd);
						GMainFrame.getInstance().setFocusedDocument(gd);
					}/*
					 * else if (element instanceof GraphElement) { GraphDocument
					 * gd = (GraphDocument) tree.getLastSelectedPathComponent();
					 * GMainFrame.getInstance().addGraphDocumentView(gd);
					 * GMainFrame.getInstance().setFocusedDocument(gd); }
					 */// Ovde sam stao
				}
			}
		});
		tree.setCellEditor(new GProjectTreeEditor(tree, new DefaultTreeCellRenderer()));
		tree.setCellRenderer(new GProjectTreeCellRendered());
		tree.setEditable(true);
		tree.addTreeSelectionListener(new GTreeSelectionListener());
		scrollPane = new JScrollPane(tree);
		tree.setSelectionPath(tree.getPathForRow(0));
	}

	public static GProjectTree getInstance() {
		if (projectTree == null) {
			projectTree = new GProjectTree();
		}
		return projectTree;
	}

	public void clearSelectionInDocuments() {
		TreePath[] allNodes = getAllNodePaths();
		for (TreePath elementPath : allNodes) {
			Object element = elementPath.getLastPathComponent();
			if (!(element instanceof GraphDocument))
				continue;

			((GraphDocument) element).getSelectedElements().clear();
		}
	}

	public TreePath[] getAllNodePaths() {
		TreeNode root = (TreeNode) tree.getModel().getRoot();

		List<TreePath> list = new ArrayList<TreePath>();

		getPaths(new TreePath(root), list);

		return (TreePath[]) list.toArray(new TreePath[list.size()]);
	}

	@SuppressWarnings("rawtypes")
	public void getPaths(TreePath parent, List<TreePath> list) {
		list.add(parent);

		TreeNode node = (TreeNode) parent.getLastPathComponent();
		if (node.getChildCount() > 0) {
			for (Enumeration e = node.children(); e.hasMoreElements();) {
				TreeNode n = (TreeNode) e.nextElement();
				TreePath path = parent.pathByAddingChild(n);
				getPaths(path, list);
			}
		}
	}

	public void setSelectionFromCanvas() {
		TreePath[] allNodes = getAllNodePaths();
		for (TreePath elementPath : allNodes) {
			Object element = elementPath.getLastPathComponent();
			if (!(element instanceof GraphElement))
				continue;

			GraphElement graphElement = (GraphElement) element;

			GraphDocument document = (GraphDocument) graphElement.getParent();
			if (document.getSelectedElements().size() == 0) {
				tree.getSelectionModel().removeSelectionPath(elementPath);
				continue;
			}

			if (document.getSelectedElements().contains(graphElement)) {
				tree.getSelectionModel().addSelectionPath(elementPath);
			} else {
				tree.getSelectionModel().removeSelectionPath(elementPath);
			}
		}
	}

	@Override
	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub

	}

}